package cn.ylz.ylmall.product.service.impl;

import cn.ylz.ylmall.account.dao.persist.repository.IUserRepository;
import cn.ylz.ylmall.account.pojo.vo.UserRoleVO;
import cn.ylz.ylmall.account.security.CurrentPrincipal;
import cn.ylz.ylmall.common.ex.ServiceException;
import cn.ylz.ylmall.common.web.ServiceCode;
import cn.ylz.ylmall.product.dao.cache.IPCommentCacheRepository;
import cn.ylz.ylmall.product.dao.persist.repository.IPCommentDetailRepository;
import cn.ylz.ylmall.product.dao.persist.repository.IPCommentRepository;
import cn.ylz.ylmall.product.dao.persist.repository.LikeRecordRepository;
import cn.ylz.ylmall.product.pojo.entity.PComment;
import cn.ylz.ylmall.product.pojo.entity.PCommentDetail;
import cn.ylz.ylmall.product.pojo.param.PCommentAddNewParam;
import cn.ylz.ylmall.product.pojo.vo.PCommentStandardVO;
import cn.ylz.ylmall.product.pojo.vo.PCommentVO;
import cn.ylz.ylmall.product.service.IPCommentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class PCommentServiceImpl implements IPCommentService {
    @Autowired
    private IPCommentRepository commentRepository;
    @Autowired
    private IPCommentDetailRepository commentDetailRepository;
    @Autowired
    private IUserRepository userRepository;
    @Autowired
    private IPCommentCacheRepository commentCacheRepository;
    @Autowired
    private LikeRecordRepository likeRecordRepository;

    @Override
    public void addNew(PCommentAddNewParam param, CurrentPrincipal currentPrincipal, HttpServletRequest req) {
        PComment comment = new PComment();
        BeanUtils.copyProperties(param, comment);
        comment.setIp(req.getRemoteAddr());
        comment.setUserId(currentPrincipal.getId());
        int rows = commentRepository.insert(comment);
        if (rows != 1) {
            String message = "发布评论失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
        String[] resourceUrls = param.getResourceUrls();
        if (resourceUrls.length!=0){
            List<PCommentDetail> commentDetails = new ArrayList<>();
            for (String resourceUrl : resourceUrls) {
                PCommentDetail pCommentDetail = new PCommentDetail();
                pCommentDetail.setCommentId(comment.getCommentId());
                pCommentDetail.setResourceUrl(resourceUrl);
                commentDetails.add(pCommentDetail);
            }
            rows = commentDetailRepository.insertBatch(commentDetails);
            if (rows < 1) {
                String message = "发布评论失败，服务器忙，请稍后再尝试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_INSERT, message);
            }
        }
    }

    @Override
    public List<PCommentVO> findByProductId(Long id) {
        List<PCommentVO> rootComments = commentRepository.listRootCommentByProductId(id);
        rootComments.forEach(this::setChildren);
        return rootComments;
    }

    @Override
    public PCommentStandardVO getStandardById(Long commentId) {
        PCommentStandardVO standard = commentRepository.getStandardById(commentId);
        if (standard==null){
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND,"此评论数据不存在");
        }
        return standard;
    }

    @Override
    public void delete(Long commentId, CurrentPrincipal currentPrincipal) {
        Long userId = currentPrincipal.getId();
        PCommentStandardVO standard = commentRepository.getStandardById(commentId);
        if (standard==null){
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND,"此评论数据不存在");
        }

        if (userId.equals(standard.getUserId()) || isAdmin(userId)) {
            // 当前用户是评论作者，可以删除评论及子评论
            deleteCommentAndChildren(commentId);
            likeRecordRepository.deleteByCommentId(commentId);
            commentDetailRepository.deleteById(commentId);
        } else {
            String message = "删除评论失败,无此操作权限";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_FORBIDDEN, message);
        }
    }

    @Override
    public Long likeComment(Long commentId, Long userId) {
        return commentCacheRepository.likeComment(commentId,userId);
    }

    @Override
    public List<Long> likeCommentByUserId(Long productId, Long userId) {
        return commentRepository.getLikedCommentsByUserAndProduct(productId,userId);
    }

    private boolean isAdmin(Long userId) {
        List<UserRoleVO> userRoles = userRepository.roleById(userId);
        return userRoles.stream().anyMatch(userRoleVO -> userRoleVO.getId() == 1L);
    }

    private void deleteCommentAndChildren(Long commentId) {
        List<PCommentVO> childComments = commentRepository.listByParentId(commentId);
        for (PCommentVO childComment : childComments) {
            deleteCommentAndChildren(childComment.getCommentId());
        }
        commentRepository.deleteById(commentId);
        commentDetailRepository.deleteById(commentId);
    }

    public void setChildren(PCommentVO pCommentVO) {
        List<PCommentVO> children = commentRepository.listByParentId(pCommentVO.getCommentId());
        if (!children.isEmpty()) {
            pCommentVO.setChildren(children);
            children.forEach(this::setChildren);
        }
    }

}
